#import <Foundation/Foundation.h>
#import "IterativeServer.h"
#import "ForkingServer.h"
#import "ThreadedServer.h"
#import <unistd.h>

static void usage( const char* program );

int main (int argc, const char * argv[])
{
    
    id server = nil;
    unsigned short serverPort = 1701;
    
    // 'server' is a custom object that implements a TCP server using one of
    // the three strategies given on the command line (i.e. iterative,
    // forking, or threading).  
    // 'serverPort' specifies the "well known" port for our service. 
     
    char ch;
    NSString *serverStrategy;
    
    // 'ch' and 'serverStrategy' are a command line processing variables
    
    
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    while ( (ch = getopt( argc, argv, "t:")) != -1 ) {
        switch (ch ) {
            case 't':
                serverStrategy = [NSString stringWithCString:optarg];
                break;
                
            default:
                usage( argv[0] );
                break;
        }
    
    }
    
    // What server strategy should we run: an iterative server, a forking concurrent
    // server, or a threaded concurrent server?  The command line argument reveals all.
    
    if ( [serverStrategy isEqualToString:@"iterative"] )
        server = [[IterativeServer alloc] initWithLocalPort: serverPort];
    else if ( [serverStrategy isEqualToString:@"forking"] )
        server = [[ForkingServer alloc] initWithLocalPort: serverPort];
    else if ( [serverStrategy isEqualToString:@"threaded"] )
        server = [[ThreadedServer alloc] initWithLocalPort: serverPort];
    else
        usage( argv[0] );
        
    
    [server run];
    // The run method implements the strategy by which the server will process
    // incoming connections.  An iterative server processes one request completely
    // before handling another.  An forking server handles requests concurrently by
    // forking a new process for each request.  A threaded server implements
    // concurrent processing by spawning a new thread for each request.
    
    [server release];
    // Shut down the server and release it from memory.
    
    [pool release];
  
    exit(0);
}


static void usage( const char* program )
{
    printf("usage: %s -t iterative | forking | threaded", program );
    exit(1);
}
